from . import passport_blu
from flask import request, abort, jsonify
from info.utils.response_code import RET  # 导入utils下面的response模块
from info.utils.captcha.captcha import captcha
from flask import current_app
from info import constants
from info import redis_store
from flask import make_response
import re
import random
from info.libs.yuntongxun.sms import CCP
from info.models import User, db
from flask import session


# passport_blu这里蓝图都是前端过来进行访问的,都在main.js进行设置
# 操作用户退出登陆,因为用户的状态存在session中,所以只要清除登录状态就可以,下次登录请求还是
# 从数据库拿号码进行比较
@passport_blu.route('/logout', methods=['POST'])
def logout():
    session.pop('user_id')
    session.pop('mobile')
    session.pop('nick_name')
    return jsonify(errno=RET.OK, errmsg='退出登陆成功')


# 实现从mysql数据库中拿数据进行登陆
@passport_blu.route('/login', methods=['POST'])
def login():
    # 接收前端ajax发过来的请求
    req_dict = request.json

    if not req_dict:
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')

    # 获取手机号码和密码
    mobile = req_dict.get('mobile')
    password = req_dict.get('password')

    # 判断手机号与密码是否为空
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')

    # 对手机号进行判断
    if not re.match(r'^1[3-9]\d{9}$', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='您的手机号码有误')

    # 在数据库中根据手机号进行查询
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询条件怕是写错了')

    # 看有没有手机号
    if not user:
        return jsonify(errno=RET.USERERR, errmsg='用户不存在')

    # 校验用户密码是否有误,利用user调用models中的check_passowrd方法进行校验
    if not user.check_passowrd(password):
        return jsonify(errno=RET.PWDERR, errmsg='登陆密码出现错误')

    # 把用户的状态存到session中
    # 记住用户的登陆状态,在前端第一页需要展示的登录或者未注册都要用到session数据判断
    # 当用户退出登录也要使用这些保存到session中的数据
    session['user_id'] = user.id
    session['mobile'] = user.mobile
    session['nick_name'] = user.nick_name

    return jsonify(errno=RET.OK, errmsg='登陆成功')


# 用户注册路由
@passport_blu.route('/register', methods=['POST'])
def register():
    # # 用户注册区域,接收参数(手机号,短信验证码,密码)
    req_dict = request.json  # 注意没有括号

    # 判断有没有数据
    if not req_dict:
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    # 手机号码
    mobile = req_dict.get('mobile')
    # 手机收到的短信
    sms_code = req_dict.get('sms_code')
    # 前端页面的密码
    password = req_dict.get('password')

    # 一次性进行判断
    if not all([mobile, sms_code, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')

    # 判断手机号码
    if not re.match(r'^1[3-9]\d{9}$', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='手机号码错误')

    # 路由路径sms_code储存的手机号码,这里进行获取其对应的值
    # 短信过期时间前端设置,已过期再点击,路由路径sms_code又会再次进行储存,这里可以获取
    try:
        real_sms_code = redis_store.get('sms_code:%s' % mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库获取短信失败')

    # 查看获取的短信验证码是否过期
    if not real_sms_code:
        return jsonify(errno=RET.NODATA, errmsg='短信验证码过期')

    # 对获前端界面输入的与数据库中的验证码进行对比
    if real_sms_code != sms_code:
        return jsonify(errno=RET.DATAERR, errmsg='短信验证出现错误')

    # 创建USER对象并把用户填入的信息保存到数据库中去
    user = User()
    # 表里面的手机号等于注册客户手机号,
    user.mobile = mobile
    user.nick_name = mobile  # 用户昵称默认为手机号

    #
    # 这里里面采用了加密,调用啦models模块user里面的password方法
    user.password = password

    # 将用户的所有信息提交到mysql数据库
    try:
        db.session.add(user)
        print(user)
        db.session.commit()
    except Exception as a:
        db.session.rollback()
        current_app.logger.error(a)
        return jsonify(errno=RET.DBERR, errmsg='保存注册用户信息失败')

    # 返回应答,则注册成功
    return jsonify(errno=RET.OK, errmsg='注册成功')


# 发送短信验证码
@passport_blu.route('/sms_code', methods=['POST'])
def send_sms_code():
    # 发送短信验证码视图函数:

    # 接收所有的json数据
    req_dict = request.json
    # 接收到后进行判断有无数据
    if not req_dict:
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')

    # 根据js中的params中的key取的value,取得对应的数据
    # 根据前端客户的输入得到手机
    mobile = req_dict.get('mobile')
    # 得到验证码
    image_code = req_dict.get('image_code')
    # 得到短信
    image_code_id = req_dict.get('image_code_id')
    # print(mobile)
    # print(image_code)
    print(image_code_id)

    # 一次性进行判断,参数是否完整
    if not all([mobile, image_code, image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')

    # 对手机好进行判断
    if not re.match(r'^1[3-9]\d{9}$', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='手机号有误')

    # 取得passport_blu.route('/image_code')存到redis中的image_code_id('下面添加的时候设置了过期时间')
    # redis设置的过期时间最好大于手机验证码过期时间
    # 取可能失败
    try:
        real_image_code = redis_store.get('image_code_id:%s' % image_code_id)  # 下面这样设置的,取一样
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='获取图片验证码失败')

    # 判断图片验证码有无过期   ? 上面判断了这里为什么还要判断
    if not real_image_code:
        return jsonify(errno=RET.NODATA, errmas='图片已经过期了')

    # 判断从前端页面获取的image_code与redis中取到的real_image_code否相同
    # 这两个都是验证码的text内容,从redis中获取的设置了过期时间
    if real_image_code != image_code:
        return jsonify(errno=RET.NODATA, errmsg='图片验证码错误')

    # 使用random.randint随机生成一个6位数
    # 以便下面使用云通讯给手机号发送这里随机生成的短信验证码
    sms_code = '%06d' % random.randint(0, 999999)
    # 这里只是为啦在操作的时候,后端方便查看,验证码
    current_app.logger.info('短信验证码为:%s' % sms_code)

    # 这里把手机验证码存到redis里面去
    try:
        # 手机好是唯一的所以作为键,验证码作为值进行保存,后面在设置过期时间
        redis_store.set('sms_code:%s' % mobile, sms_code, constants.SMS_CODE_REDIS_EXPIRES)

    except Exception as a:
        current_app.logger.error(a)
        return jsonify(errno=RET.DBERR, errmsg='保存短信验证码失败')
    # 使用云通讯给给售号码发送短信
    # 调用对应文件夹里面的模块进行短信的发送.里面根据被调用体的要求,填写相应的内容
    # 分别对应手机号,随机的生成数,过期时间,1为被调用函数模块名意义不大
    res = CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES / 60], 1)
    #
    # # 根据文档可知,返回0表示成功,其余表示失败,也就是不等于0(res接收进行判断)
    # # 根据被调用函数进行判断,不等于0则表示发送失败
    if res != 0:
        return jsonify(errno=RET.THIRDERR, errmsg='发送短信失败3333')
    #
    # # 返回数据被前端接收,前端根据判断操作进行展示,ok对应0,前端拿这个进行判断
    return jsonify(errno=RET.OK, errmsg='发送短信成功')


# 这是图片验证码区域路由
@passport_blu.route('/image_code')
def get_image_code():
    """
    产生图片验证码:

    """
    # 获取路径后面带过来的参数,这里的参数有前端随机生成的imageCodeId = generateUUID();
    image_code_id = request.args.get('image_code_id')
    # print('999999999999999获面带过来的参数%s' % image_code_id)
    # 首先判断有没有参数,没有返回指定数据
    if not image_code_id:
        # abort(400)
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')

    # 产生图片验证码name为图文名称,text为验证码文本(如ZSV4),content为验证码图片内容
    # 这个为调用utils里面的captcha类,并调用方法generate_captcha产生验证码,这个方法已经指定
    # 返回的数据有三个,这边进行接收就可以name, text, content
    name, text, content = captcha.generate_captcha()
    current_app.logger.info('图片验证码为:%s' % text)
    print(name, text, content, 555555555555)

    #
    # 将验证码文本保存到redis数据库中,图片验证码编号为,也就是前端的uuid为key,文本text为value
    # constants.IMAGE_CODE_REDIS_EXPIRES设置过期时间的
    try:
        redis_store.set('image_code_id:%s' % image_code_id, text, constants.IMAGE_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='保存图片验证码失败')

    ### ? 为什么返回的是content
    # 返回图片验证码
    response = make_response(content)
    print(content)
    print(response)
    # 设置在相应头中进行返回
    response.headers['Content_Type'] = 'image/jpg'
    return response

# 保存在redis和mysql中的数据有哪些
# 默认加载首页搞清楚
# 为什么图片验证码设置在相应头里面
# 保存uuid和text哪里用到啦
